﻿Imports System
Imports System.Collections.Generic
Imports System.Drawing
Imports System.Windows.Forms
Imports System.Workflow.ComponentModel

Namespace System.Workflow.ComponentModel.Design
    Friend NotInheritable Class FreeFormDragDropManager
        Inherits DragDropManager
        ' Methods
        Protected Overrides Sub CreateDragFeedbackImages(ByVal draggedActivities As IList([Of] Activity))
            MyBase.CreateDragFeedbackImages(draggedActivities)
            Dim list As New List([Of] Image)
            [Using] graphics As Graphics = MyBase.ParentView.CreateGraphics
                Dim activity As Activity
                For Each activity In draggedActivities
                    Dim designer As ActivityDesigner = ActivityDesigner.GetDesigner(activity)
                    If (designer Is Nothing) Then
                        designer = ActivityDesigner.CreateDesigner(MyBase.ParentView, activity)
                    End If
                    list.Add(designer.GetPreviewImage(graphics))
                Next
            End [Using]
            MyBase.ParentView.InvalidateClientRectangle(Rectangle.Empty)
            Me.draggedDesignerImages = list
        End Sub

        Protected Overrides Sub DestroyDragFeedbackImages()
            MyBase.DestroyDragFeedbackImages
            If (Not Me.draggedDesignerImages Is Nothing) Then
                Dim bitmap As Bitmap
                For Each bitmap In Me.draggedDesignerImages
                    bitmap.Dispose
                Next
                Me.draggedDesignerImages = Nothing
                MyBase.ParentView.InvalidateClientRectangle(Rectangle.Empty)
            End If
        End Sub

        Friend Shared Function GetDesignerLocations(ByVal startPoint As Point, ByVal endPoint As Point, ByVal activitiesToMove As ICollection([Of] Activity)) As Point()
            Dim list As New List([Of] Point)
            Dim activity As Activity
            For Each activity In activitiesToMove
                Dim location As Point = endPoint
                Dim designer As ActivityDesigner = ActivityDesigner.GetDesigner(activity)
                If ((Not designer Is Nothing) AndAlso Not startPoint.IsEmpty) Then
                    Dim size As New Size((endPoint.X - startPoint.X), (endPoint.Y - startPoint.Y))
                    location = New Point((designer.Location.X + size.Width), (designer.Location.Y + size.Height))
                End If
                location = DesignerHelpers.SnapToGrid(location)
                list.Add(location)
            Next
            Return list.ToArray
        End Function

        Private Sub InvalidateDraggedImages(ByVal locations As Point())
            If ((Not Me.draggedDesignerImages Is Nothing) AndAlso (locations.Length = Me.draggedDesignerImages.Count)) Then
                Dim ambientTheme As AmbientTheme = WorkflowTheme.CurrentTheme.AmbientTheme
                Dim parentView As WorkflowView = MyBase.ParentView
                Dim i As Integer
                For i = 0 To Me.draggedDesignerImages.Count - 1
                    Dim logicalRectangle As New Rectangle(locations(i), Me.draggedDesignerImages.Item(i).Size)
                    logicalRectangle.Inflate((2 * ambientTheme.Margin.Width), (2 * ambientTheme.Margin.Height))
                    parentView.InvalidateLogicalRectangle(logicalRectangle)
                Next i
            End If
        End Sub

        Protected Overrides Function OnDragEnter(ByVal eventArgs As DragEventArgs) As Boolean
            Dim flag As Boolean = MyBase.OnDragEnter(eventArgs)
            If (Me.draggedDesignerImages Is Nothing) Then
                Dim parentView As WorkflowView = MyBase.ParentView
                Dim clientPoint As Point = parentView.PointToClient(New Point(eventArgs.X, eventArgs.Y))
                Dim point2 As Point = parentView.ScreenPointToLogical(New Point(eventArgs.X, eventArgs.Y))
                If parentView.IsClientPointInActiveLayout(clientPoint) Then
                    Me.movedDesignerImagePoint = point2
                    Return flag
                End If
                Me.movedDesignerImagePoint = MyBase.DragInitiationPoint
            End If
            Return flag
        End Function

        Protected Overrides Function OnDragOver(ByVal eventArgs As DragEventArgs) As Boolean
            If (Not Me.draggedDesignerImages Is Nothing) Then
                Dim locations As Point() = FreeFormDragDropManager.GetDesignerLocations(MyBase.DragInitiationPoint, Me.movedDesignerImagePoint, MyBase.DraggedActivities)
                Me.InvalidateDraggedImages(locations)
            End If
            Dim flag As Boolean = MyBase.OnDragOver(eventArgs)
            If (Not Me.draggedDesignerImages Is Nothing) Then
                Dim parentView As WorkflowView = MyBase.ParentView
                Dim clientPoint As Point = parentView.PointToClient(New Point(eventArgs.X, eventArgs.Y))
                Dim point2 As Point = parentView.ScreenPointToLogical(New Point(eventArgs.X, eventArgs.Y))
                If parentView.IsClientPointInActiveLayout(clientPoint) Then
                    Me.movedDesignerImagePoint = point2
                Else
                    Me.movedDesignerImagePoint = MyBase.DragInitiationPoint
                End If
                Dim pointArray2 As Point() = FreeFormDragDropManager.GetDesignerLocations(MyBase.DragInitiationPoint, Me.movedDesignerImagePoint, MyBase.DraggedActivities)
                Me.InvalidateDraggedImages(pointArray2)
            End If
            Return flag
        End Function

        Protected Overrides Function OnGiveFeedback(ByVal gfbevent As GiveFeedbackEventArgs) As Boolean
            MyBase.OnGiveFeedback(gfbevent)
            If (Me.draggedDesignerImages Is Nothing) Then
                Return False
            End If
            gfbevent.UseDefaultCursors = False
            If ((gfbevent.Effect And DragDropEffects.Move) = DragDropEffects.Move) Then
                Cursor.Current = FreeFormDragDropManager.DragMoveCursor
            ElseIf ((gfbevent.Effect And DragDropEffects.Copy) = DragDropEffects.Copy) Then
                Cursor.Current = FreeFormDragDropManager.DragCopyCursor
            Else
                Cursor.Current = Cursors.No
            End If
            Return True
        End Function

        Protected Overrides Function OnMouseLeave() As Boolean
            Me.UpdateCursor(False)
            Return False
        End Function

        Protected Overrides Function OnMouseMove(ByVal eventArgs As MouseEventArgs) As Boolean
            Dim flag As Boolean = MyBase.OnMouseMove(eventArgs)
            If (eventArgs.Button = MouseButtons.None) Then
                Dim showMoveCursor As Boolean = False
                showMoveCursor = (showMoveCursor Or ((((Not MyBase.MessageHitTestContext Is Nothing) AndAlso (Not MyBase.MessageHitTestContext.AssociatedDesigner Is Nothing)) AndAlso TypeOf ActivityDesigner.GetParentDesigner(MyBase.MessageHitTestContext.AssociatedDesigner.Activity) Is FreeformActivityDesigner) AndAlso ((MyBase.MessageHitTestContext.HitLocation And HitTestLocations.ActionArea) = HitTestLocations.None)))
                Me.UpdateCursor(showMoveCursor)
            End If
            Return flag
        End Function

        Protected Overrides Function OnPaint(ByVal eventArgs As PaintEventArgs, ByVal viewPort As Rectangle, ByVal ambientTheme As AmbientTheme) As Boolean
            Dim flag As Boolean = False
            If ((Not Me.draggedDesignerImages Is Nothing) AndAlso TypeOf MyBase.DropTargetDesigner Is FreeformActivityDesigner) Then
                [Using] region As Region = New Region(ActivityDesignerPaint.GetDesignerPath(MyBase.ParentView.RootDesigner, False))
                    Dim clip As Region = eventArgs.Graphics.Clip
                    eventArgs.Graphics.Clip = [region]
                    Dim pointArray As Point() = FreeFormDragDropManager.GetDesignerLocations(MyBase.DragInitiationPoint, Me.movedDesignerImagePoint, MyBase.DraggedActivities)
                    Dim i As Integer
                    For i = 0 To Me.draggedDesignerImages.Count - 1
                        Dim size As Size = Me.draggedDesignerImages.Item(i).Size
                        ActivityDesignerPaint.DrawImage(eventArgs.Graphics, Me.draggedDesignerImages.Item(i), New Rectangle(New Point((pointArray(i).X - (2 * ambientTheme.Margin.Width)), (pointArray(i).Y - (2 * ambientTheme.Margin.Height))), size), New Rectangle(Point.Empty, size), DesignerContentAlignment.Fill, 0.4!, False)
                    Next i
                    eventArgs.Graphics.Clip = clip
                    Return flag
                End [Using]
            End If
            Return MyBase.OnPaint(eventArgs, viewPort, ambientTheme)
        End Function

        Protected Overrides Function OnPaintWorkflowAdornments(ByVal eventArgs As PaintEventArgs, ByVal viewPort As Rectangle, ByVal ambientTheme As AmbientTheme) As Boolean
            Dim flag As Boolean = False
            If (((Not Me.draggedDesignerImages Is Nothing) AndAlso (Me.draggedDesignerImages.Count <> 0)) AndAlso TypeOf MyBase.DropTargetDesigner Is FreeformActivityDesigner) Then
                Return flag
            End If
            Return MyBase.OnPaintWorkflowAdornments(eventArgs, viewPort, ambientTheme)
        End Function

        Protected Overrides Function OnScroll(ByVal sender As ScrollBar, ByVal value As Integer) As Boolean
            If (Not Me.draggedDesignerImages Is Nothing) Then
                Dim locations As Point() = FreeFormDragDropManager.GetDesignerLocations(MyBase.DragInitiationPoint, Me.movedDesignerImagePoint, MyBase.DraggedActivities)
                Me.InvalidateDraggedImages(locations)
            End If
            Dim flag As Boolean = MyBase.OnScroll(sender, value)
            If (Not Me.draggedDesignerImages Is Nothing) Then
                Dim parentView As WorkflowView = MyBase.ParentView
                Dim clientPoint As Point = parentView.PointToClient(Control.MousePosition)
                Dim point2 As Point = parentView.ScreenPointToLogical(Control.MousePosition)
                If parentView.IsClientPointInActiveLayout(clientPoint) Then
                    Me.movedDesignerImagePoint = point2
                Else
                    Me.movedDesignerImagePoint = MyBase.DragInitiationPoint
                End If
                Dim pointArray2 As Point() = FreeFormDragDropManager.GetDesignerLocations(MyBase.DragInitiationPoint, Me.movedDesignerImagePoint, MyBase.DraggedActivities)
                Me.InvalidateDraggedImages(pointArray2)
            End If
            Return flag
        End Function

        Private Sub UpdateCursor(ByVal showMoveCursor As Boolean)
            If showMoveCursor Then
                If ((Not MyBase.ParentView.Cursor Is FreeFormDragDropManager.MoveCursor) AndAlso (MyBase.ParentView.Cursor Is Cursors.Default)) Then
                    Me.previousCursor = MyBase.ParentView.Cursor
                    MyBase.ParentView.Cursor = FreeFormDragDropManager.MoveCursor
                End If
            Else
                MyBase.ParentView.Cursor = Me.previousCursor
            End If
        End Sub


        ' Fields
        Private Shared DragCopyCursor As Cursor = New Cursor(GetType(WorkflowView), "Resources.DragCopyCursor.cur")
        Private draggedDesignerImages As List([Of] Image)
        Private Shared DragMoveCursor As Cursor = New Cursor(GetType(WorkflowView), "Resources.DragMoveCursor.cur")
        Private Shared MoveCursor As Cursor = New Cursor(GetType(WorkflowView), "Resources.MoveCursor.cur")
        Private movedDesignerImagePoint As Point = Point.Empty
        Private previousCursor As Cursor = Cursors.Default
    End Class
End Namespace

